package com.vehiclemanagement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vehiclemanagement.entity.Driver;
import com.vehiclemanagement.entity.ETCCard;
import com.vehiclemanagement.entity.ETCParking;
import com.vehiclemanagement.entity.Vehicle;
import com.vehiclemanagement.mapper.ETCParkingMapper;
import com.vehiclemanagement.service.DriverService;
import com.vehiclemanagement.service.ETCCardService;
import com.vehiclemanagement.service.ETCParkingService;
import com.vehiclemanagement.service.VehicleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.Year;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * ETC停车记录服务实现类
 */
@Service
@Slf4j
public class ETCParkingServiceImpl extends ServiceImpl<ETCParkingMapper, ETCParking> implements ETCParkingService {

    @Autowired
    private VehicleService vehicleService;
    
    @Autowired
    private DriverService driverService;
    
    @Autowired
    private ETCCardService etcCardService;

    @Override
    public IPage<ETCParking> pageParking(Integer current, Integer size, String searchTerm, 
                                        Long vehicleId, Long driverId, Long etcCardId, 
                                        Integer parkingType, Integer status, 
                                        LocalDateTime startTime, LocalDateTime endTime) {
        log.info("分页查询ETC停车记录: current={}, size={}, searchTerm={}, vehicleId={}, driverId={}, etcCardId={}, parkingType={}, status={}, startTime={}, endTime={}",
                current, size, searchTerm, vehicleId, driverId, etcCardId, parkingType, status, startTime, endTime);

        Page<ETCParking> page = new Page<>(current, size);
        
        // 构建查询条件
        StringBuilder whereSql = new StringBuilder();
        whereSql.append(" 1=1 ");
        
        // 搜索条件
        if (StringUtils.hasText(searchTerm)) {
            whereSql.append(" AND (v.plate_number LIKE '%").append(searchTerm).append("%'")
                    .append(" OR d.name LIKE '%").append(searchTerm).append("%'")
                    .append(" OR ec.card_number LIKE '%").append(searchTerm).append("%'")
                    .append(" OR p.parking_name LIKE '%").append(searchTerm).append("%'")
                    .append(" OR p.transaction_no LIKE '%").append(searchTerm).append("%')");
        }
        
        // 车辆ID
        if (vehicleId != null) {
            whereSql.append(" AND p.vehicle_id = ").append(vehicleId);
        }
        
        // 驾驶员ID
        if (driverId != null) {
            whereSql.append(" AND p.driver_id = ").append(driverId);
        }
        
        // ETC卡ID
        if (etcCardId != null) {
            whereSql.append(" AND p.etc_card_id = ").append(etcCardId);
        }
        
        // 停车类型
        if (parkingType != null) {
            whereSql.append(" AND p.parking_type = ").append(parkingType);
        }
        
        // 状态
        if (status != null) {
            whereSql.append(" AND p.status = ").append(status);
        }
        
        // 时间范围（基于入场时间）
        if (startTime != null) {
            whereSql.append(" AND p.entry_time >= '").append(startTime).append("'");
        }
        
        if (endTime != null) {
            whereSql.append(" AND p.entry_time <= '").append(endTime).append("'");
        }
        
        // 执行分页查询
        IPage<ETCParking> result = baseMapper.selectPageWithInfo(page, whereSql.toString());
        
        // 填充停车类型和状态名称
        result.getRecords().forEach(this::fillParkingTypeAndStatusName);
        
        return result;
    }

    @Override
    public ETCParking getParkingById(Long id) {
        log.info("获取ETC停车记录详情: id={}", id);
        
        if (id == null) {
            log.error("获取ETC停车记录详情失败：ID为空");
            return null;
        }
        
        ETCParking parking = getById(id);
        
        if (parking != null) {
            // 获取关联信息
            Vehicle vehicle = vehicleService.getById(parking.getVehicleId());
            Driver driver = driverService.getById(parking.getDriverId());
            ETCCard etcCard = etcCardService.getById(parking.getEtcCardId());
            
            if (vehicle != null) {
                parking.setPlateNumber(vehicle.getPlateNumber());
            }
            
            if (driver != null) {
                parking.setDriverName(driver.getName());
            }
            
            if (etcCard != null) {
                parking.setEtcCardNumber(etcCard.getCardNumber());
            }
            
            // 填充类型和状态名称
            fillParkingTypeAndStatusName(parking);
        }
        
        return parking;
    }

    @Override
    @Transactional
    public boolean addParking(ETCParking parking) {
        log.info("添加ETC停车记录: {}", parking);
        
        if (parking == null) {
            log.error("添加ETC停车记录失败：参数为空");
            return false;
        }
        
        // 设置默认值
        if (parking.getStatus() == null) {
            parking.setStatus(1); // 1:已创建
        }
        
        if (parking.getDelFlag() == null) {
            parking.setDelFlag(0); // 0:未删除
        }
        
        // 设置创建和更新时间
        LocalDateTime now = LocalDateTime.now();
        parking.setCreateTime(now);
        parking.setUpdateTime(now);
        
        return save(parking);
    }

    @Override
    @Transactional
    public boolean updateParking(ETCParking parking) {
        log.info("更新ETC停车记录: {}", parking);
        
        if (parking == null || parking.getId() == null) {
            log.error("更新ETC停车记录失败：参数为空或ID为空");
            return false;
        }
        
        ETCParking existParking = getById(parking.getId());
        if (existParking == null) {
            log.error("更新ETC停车记录失败：记录不存在, id={}", parking.getId());
            return false;
        }
        
        // 设置更新时间
        parking.setUpdateTime(LocalDateTime.now());
        
        // 如果设置了出场时间和入场时间，计算停车时长（单位：分钟）
        if (parking.getEntryTime() != null && parking.getExitTime() != null) {
            long minutes = Duration.between(parking.getEntryTime(), parking.getExitTime()).toMinutes();
            parking.setDuration((int) minutes);
        }
        
        return updateById(parking);
    }

    @Override
    @Transactional
    public boolean deleteParking(Long id) {
        log.info("删除ETC停车记录: id={}", id);
        
        if (id == null) {
            log.error("删除ETC停车记录失败：ID为空");
            return false;
        }
        
        ETCParking parking = getById(id);
        if (parking == null) {
            log.error("删除ETC停车记录失败：记录不存在, id={}", id);
            return false;
        }
        
        // 逻辑删除（依赖于MyBatis-Plus的@TableLogic注解）
        return removeById(id);
    }

    @Override
    @Transactional
    public boolean settleParking(Long id) {
        log.info("结算ETC停车记录: id={}", id);
        
        if (id == null) {
            log.error("结算ETC停车记录失败：ID为空");
            return false;
        }
        
        ETCParking parking = getById(id);
        if (parking == null) {
            log.error("结算ETC停车记录失败：记录不存在, id={}", id);
            return false;
        }
        
        // 检查记录状态是否为已创建
        if (parking.getStatus() != 1) {
            log.error("结算ETC停车记录失败：记录状态不是已创建, id={}, status={}", id, parking.getStatus());
            return false;
        }
        
        // 检查是否已设置出场时间和费用
        if (parking.getExitTime() == null) {
            log.error("结算ETC停车记录失败：出场时间未设置, id={}", id);
            return false;
        }
        
        if (parking.getFee() == null || parking.getFee().compareTo(BigDecimal.ZERO) < 0) {
            log.error("结算ETC停车记录失败：费用未设置或无效, id={}, fee={}", id, parking.getFee());
            return false;
        }
        
        // 从ETC卡中扣除费用
        ETCCard etcCard = etcCardService.getById(parking.getEtcCardId());
        if (etcCard == null) {
            log.error("结算ETC停车记录失败：找不到对应的ETC卡, id={}, etcCardId={}", id, parking.getEtcCardId());
            return false;
        }
        
        // 检查ETC卡余额是否足够
        if (etcCard.getBalance().compareTo(parking.getFee()) < 0) {
            log.error("结算ETC停车记录失败：ETC卡余额不足, id={}, etcCardId={}, balance={}, fee={}", 
                    id, parking.getEtcCardId(), etcCard.getBalance(), parking.getFee());
            return false;
        }
        
        // 更新ETC卡余额
        BigDecimal newBalance = etcCard.getBalance().subtract(parking.getFee());
        LambdaUpdateWrapper<ETCCard> cardUpdateWrapper = new LambdaUpdateWrapper<>();
        cardUpdateWrapper.eq(ETCCard::getId, etcCard.getId())
                         .set(ETCCard::getBalance, newBalance)
                         .set(ETCCard::getUpdateTime, LocalDateTime.now());
        boolean cardUpdateResult = etcCardService.update(cardUpdateWrapper);
        
        if (!cardUpdateResult) {
            log.error("结算ETC停车记录失败：更新ETC卡余额失败, id={}, etcCardId={}", id, parking.getEtcCardId());
            return false;
        }
        
        // 更新停车记录状态为已结算
        LambdaUpdateWrapper<ETCParking> parkingUpdateWrapper = new LambdaUpdateWrapper<>();
        parkingUpdateWrapper.eq(ETCParking::getId, id)
                            .set(ETCParking::getStatus, 2) // 2:已结算
                            .set(ETCParking::getUpdateTime, LocalDateTime.now());
        
        boolean parkingUpdateResult = update(parkingUpdateWrapper);
        
        if (parkingUpdateResult) {
            log.info("结算ETC停车记录成功, id={}, fee={}", id, parking.getFee());
            return true;
        } else {
            log.error("结算ETC停车记录失败：更新停车记录状态失败, id={}", id);
            // 如果更新停车记录失败，应该回滚事务
            return false;
        }
    }

    @Override
    @Transactional
    public int batchSettleParking(List<Long> ids) {
        log.info("批量结算ETC停车记录: ids={}", ids);
        
        if (ids == null || ids.isEmpty()) {
            log.error("批量结算ETC停车记录失败：ID列表为空");
            return 0;
        }
        
        int successCount = 0;
        
        for (Long id : ids) {
            try {
                boolean result = settleParking(id);
                if (result) {
                    successCount++;
                }
            } catch (Exception e) {
                log.error("批量结算ETC停车记录异常, id=" + id, e);
                // 继续处理下一条记录
            }
        }
        
        log.info("批量结算ETC停车记录完成: 总数={}, 成功数={}", ids.size(), successCount);
        return successCount;
    }

    @Override
    @Transactional
    public boolean recordExit(Long id, LocalDateTime exitTime, BigDecimal fee) {
        log.info("记录ETC停车出场信息: id={}, exitTime={}, fee={}", id, exitTime, fee);
        
        if (id == null || exitTime == null || fee == null) {
            log.error("记录ETC停车出场信息失败：参数不完整");
            return false;
        }
        
        ETCParking parking = getById(id);
        if (parking == null) {
            log.error("记录ETC停车出场信息失败：记录不存在, id={}", id);
            return false;
        }
        
        // 检查入场时间是否存在
        if (parking.getEntryTime() == null) {
            log.error("记录ETC停车出场信息失败：入场时间未设置, id={}", id);
            return false;
        }
        
        // 确保出场时间晚于入场时间
        if (exitTime.isBefore(parking.getEntryTime())) {
            log.error("记录ETC停车出场信息失败：出场时间早于入场时间, id={}, entryTime={}, exitTime={}", 
                    id, parking.getEntryTime(), exitTime);
            return false;
        }
        
        // 计算停车时长（分钟）
        long minutes = Duration.between(parking.getEntryTime(), exitTime).toMinutes();
        
        // 更新停车记录
        LambdaUpdateWrapper<ETCParking> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(ETCParking::getId, id)
                    .set(ETCParking::getExitTime, exitTime)
                    .set(ETCParking::getDuration, (int) minutes)
                    .set(ETCParking::getFee, fee)
                    .set(ETCParking::getUpdateTime, LocalDateTime.now());
        
        boolean result = update(updateWrapper);
        
        if (result) {
            log.info("记录ETC停车出场信息成功, id={}, duration={}, fee={}", id, minutes, fee);
            return true;
        } else {
            log.error("记录ETC停车出场信息失败：更新记录失败, id={}", id);
            return false;
        }
    }

    @Override
    public BigDecimal sumFeeByVehicleId(Long vehicleId) {
        log.info("获取车辆停车总费用: vehicleId={}", vehicleId);
        
        if (vehicleId == null) {
            log.error("获取车辆停车总费用失败：车辆ID为空");
            return BigDecimal.ZERO;
        }
        
        // 调用Mapper方法获取总费用
        return baseMapper.sumFeeByVehicleId(vehicleId, null, null);
    }

    @Override
    public BigDecimal sumFeeByEtcCardId(Long etcCardId) {
        log.info("获取ETC卡停车总费用: etcCardId={}", etcCardId);
        
        if (etcCardId == null) {
            log.error("获取ETC卡停车总费用失败：ETC卡ID为空");
            return BigDecimal.ZERO;
        }
        
        // 调用Mapper方法获取总费用
        return baseMapper.sumFeeByEtcCardId(etcCardId, null, null);
    }

    @Override
    public BigDecimal sumFeeByDriverId(Long driverId) {
        log.info("获取驾驶员停车总费用: driverId={}", driverId);
        
        if (driverId == null) {
            log.error("获取驾驶员停车总费用失败：驾驶员ID为空");
            return BigDecimal.ZERO;
        }
        
        // 调用Mapper方法获取总费用
        return baseMapper.sumFeeByDriverId(driverId, null, null);
    }

    @Override
    public List<Map<String, Object>> statisticsByMonth(Integer year) {
        log.info("获取按月统计数据: year={}", year);
        
        // 如果未指定年份，使用当前年份
        if (year == null) {
            year = LocalDateTime.now().getYear();
        }
        
        // 调用Mapper方法获取按月统计数据
        return baseMapper.statisticsByMonth(year, null);
    }

    @Override
    public List<Map<String, Object>> statisticsByParkingType(LocalDateTime startTime, LocalDateTime endTime) {
        log.info("获取按停车类型统计的数据: startTime={}, endTime={}", startTime, endTime);
        
        // 如果未提供时间范围，默认查询最近一年的数据
        if (startTime == null) {
            startTime = LocalDateTime.now().minusYears(1);
        }
        
        if (endTime == null) {
            endTime = LocalDateTime.now();
        }
        
        // 获取当前年份和月份
        int year = LocalDateTime.now().getYear();
        int month = LocalDateTime.now().getMonthValue();
        
        // 调用Mapper方法获取按类型统计数据
        return baseMapper.getETCParkingStatistics(year, month);
    }
    
    /**
     * 填充停车类型和状态名称
     */
    private void fillParkingTypeAndStatusName(ETCParking parking) {
        if (parking == null) {
            return;
        }
        
        // 停车类型名称
        if (parking.getParkingType() != null) {
            switch (parking.getParkingType()) {
                case 1:
                    parking.setParkingTypeName("路边停车");
                    break;
                case 2:
                    parking.setParkingTypeName("停车场");
                    break;
                case 3:
                    parking.setParkingTypeName("地下车库");
                    break;
                default:
                    parking.setParkingTypeName("未知");
            }
        }
        
        // 状态名称
        if (parking.getStatus() != null) {
            switch (parking.getStatus()) {
                case 1:
                    parking.setStatusName("已创建");
                    break;
                case 2:
                    parking.setStatusName("已结算");
                    break;
                case 3:
                    parking.setStatusName("异常");
                    break;
                default:
                    parking.setStatusName("未知");
            }
        }
    }
} 